package com.yh.lq.robot;

import com.alibaba.fastjson.JSONObject;
import com.yh.lq.LQGlobal;
import com.yh.lq.boot.LQProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.WebSocketSession;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

/**
 * API处理类
 */
@Slf4j
public class ApiHandler {
    private AtomicLong apiEcho = new AtomicLong(0);//用于标记是哪次发送api，接受时作为key放入apiResponseMap

    private Map<String, ApiSender> apiCallbackMap = new HashMap<>();//用于存放api调用，收到响应时put，处理完成remove

    LQProperties lqProperties;

    public ApiHandler(LQProperties cqProperties) {
        this.lqProperties = cqProperties;
    }

    /**
     * 收到 以前调用的API 的响应
     *
     * @param message 内容
     */
    public void onReceiveApiMessage(JSONObject message) {
        String echo = message.getString(LQGlobal.echo);
        ApiSender apiSender = apiCallbackMap.get(echo);
        if (apiSender instanceof ApiBlockSender) {
            ApiBlockSender apiBlockSender = (ApiBlockSender) apiSender;
            apiBlockSender.onReceiveJson(message);
        }
        if (apiSender instanceof ApiMessageSender) {
            ApiMessageSender apiMessageSender = (ApiMessageSender) apiSender;
            apiMessageSender.onReceiveJson(message);
        }
        apiCallbackMap.remove(echo);
    }


    /**
     * 构造API需要的json，使用预定义的Enum
     *
     * @param action 需要调用的API
     * @param params 参数
     * @return 结果
     */
    private JSONObject constructApiJSON(ApiEnum action, JSONObject params) {
        if (params == null) {
            params = new JSONObject();
        }
        params.put("Api", action.getUrl());
        params.put(LQGlobal.echo, apiEcho.addAndGet(1));
        return params;
    }

    /**
     * 调用定义好的API
     *
     * @param botSession 机器人session
     * @param action     执行的操作
     * @param params     参数
     * @return 结果 不关心具体结果
     */
    public JSONObject sendApiMessage(WebSocketSession botSession, ApiEnum action, JSONObject params) {
        JSONObject apiJSON = constructApiJSON(action, params);
        ApiMessageSender apiMessageSender = new ApiMessageSender(botSession, lqProperties.getRobotSecretKey(), lqProperties.getApiTimeout());
        return sendApiNoSync(apiJSON, apiMessageSender);
    }

    /**
     * 调用定义好的API
     *
     * @param botSession 机器人session
     * @param action     执行的操作
     * @param params     参数
     * @return 结果 需要获取结果,此方法加锁
     */
    synchronized public JSONObject sendApiBlock(WebSocketSession botSession, ApiEnum action, JSONObject params) {
        JSONObject apiJSON = constructApiJSON(action, params);
        ApiBlockSender apiBlockSender = new ApiBlockSender(botSession, lqProperties.getApiTimeout(), lqProperties.getRobotSecretKey());
        return sendApi(apiJSON, apiBlockSender);
    }


    synchronized private JSONObject sendApi(JSONObject apiJson, ApiSender apiSender) {
        String echo = apiJson.getString(LQGlobal.echo);
        apiCallbackMap.put(echo, apiSender);
        JSONObject retJson;
        try {
            retJson = apiSender.sendApiJson(apiJson);
        } catch (Exception e) {
            log.error("", e);
            retJson = new JSONObject();
            retJson.put("msg", "failed");
            retJson.put("code", -1);
        } finally {
            apiCallbackMap.remove(echo);
        }
        return retJson;
    }

    private JSONObject sendApiNoSync(JSONObject apiJson, ApiSender apiSender) {
        String echo = apiJson.getString(LQGlobal.echo);
        apiCallbackMap.put(echo, apiSender);
        JSONObject retJson;
        try {
            retJson = apiSender.sendApiJson(apiJson);
            if (retJson == null) {
                retJson = new JSONObject();
                retJson.put("msg", "消息发送超时");
                retJson.put("code", -2);
            }
        } catch (Exception e) {
            log.error("", e);
            retJson = new JSONObject();
            retJson.put("msg", "failed");
            retJson.put("code", -1);
        } finally {
            apiCallbackMap.remove(echo);
        }
        return retJson;
    }
}
